/**
 * 
 */
package at.ac.tuwien.swa075.telco.auc.service;

import at.ac.tuwien.swa075.telco.auc.AucException;
import at.ac.tuwien.swa075.telco.auc.AuthenticationException;
import at.ac.tuwien.swa075.telco.auc.AuthenticationStatus;
import at.ac.tuwien.swa075.telco.auc.dao.IProfileDAO;
import at.ac.tuwien.swa075.telco.auc.dao.ProfileDAOFactory;
import at.ac.tuwien.swa075.telco.auc.dao.ProfileTO;

/**
 * This class implements the service interfaces provided by the authentication
 * center.
 * 
 * @author Johannes Mayr <johannes.mayr@chello.at>
 */
public class AuthenticationCenter implements IAuthenticationService, IProfile, ISecurityAdministration {
	
	/**
	 * Validates the subscriber against his pin code.
	 * 
	 * @param imsi
	 *            The subscriber id to verify.
	 * @param pin
	 *            The pin code.
	 * @return True if the pin code matches the pin code in the auc.
	 * @throws AuthenticationException
	 *             An error occured during authentication.
	 */
	public boolean validateSubscriber(String imsi, String pin) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profileTO = profileDAO.findProfile(imsi);
		if (!profileTO.status.equals(AuthenticationStatus.ACTIVE)) {
			return false;
		}
		if (!profileTO.pin.equals(pin)) {
			if (profileTO.failureCount >= 2) {
				profileTO.status = AuthenticationStatus.LOCKED;
			}
			profileTO.failureCount++;
			profileDAO.updateProfile(profileTO);
			return false;
		}
		profileTO.failureCount = 0;
		profileDAO.updateProfile(profileTO);
		return true;
	}

	/**
	 * Resets the pin code.
	 * 
	 * @param imsi
	 *            The subscriber identity.
	 * @param pin
	 *            The new pin code to set.
	 * @throws AucException
	 *             An error occured during the pin reset.
	 */
	public void resetPin(String imsi, String pin) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profileTO = profileDAO.findProfile(imsi);
		profileTO.pin = pin;
		profileDAO.updateProfile(profileTO);
	}

	/**
	 * Activates a deactivated or newly created authentication profile.
	 * 
	 * @param imsi
	 *            The subscriber identity to activate.
	 * @throws AucException
	 *             An error occured during the activation.
	 */
	public void activateSubscriber(String imsi) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profileTO = profileDAO.findProfile(imsi);
		profileTO.status = AuthenticationStatus.ACTIVE;
		profileTO.failureCount = 0;
		profileDAO.updateProfile(profileTO);
	}

	/**
	 * Adds a subscriber authentication to the AUC.
	 * 
	 * @param imsi
	 *            The subscriber identity.
	 * @param pin
	 *            The pin code.
	 * @throws AucException
	 *             An error occured while creating the subscriber
	 *             authentication.
	 */
	public void addProfile(String imsi, String pin) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profile = new ProfileTO();
		profile.failureCount = 0;
		profile.imsi = imsi;
		profile.pin = pin;
		profile.status = AuthenticationStatus.CREATED;
		profileDAO.insertProfile(profile);
	}

	public boolean deleteProfile(String imsi) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profile = profileDAO.findProfile(imsi);
		if (profile.status.equals(AuthenticationStatus.DELETED)) {
			return false;
		}
		profile.status = AuthenticationStatus.DELETED;
		profileDAO.updateProfile(profile);
		return true;
	}

	/**
	 * Deletes an authentication profile.
	 * 
	 * @param imsi
	 *            The subscriber identity .
	 * @return True if the profile has been deleted.
	 * @throws AucException
	 *             An error occured during the delete operation.
	 */
	public boolean existsProfile(String imsi) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profile = profileDAO.findProfile(imsi);
		if (profile == null) {
			return false;
		}
		if (!profile.imsi.equals(imsi)) {
			return false;
		}
		return true;
	}

	/**
	 * Deactivates an authentication profile. After all future logons are
	 * denied.
	 * 
	 * @param imsi
	 *            The subscriber identity.
	 * @throws AucException
	 *             An error occured while deactivating the subscriber.
	 */
	public void deactivateSubscriber(String imsi) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profile = profileDAO.findProfile(imsi);
		profile.status = AuthenticationStatus.LOCKED;
		profileDAO.updateProfile(profile);
	}

	/**
	 * Returns the current AuthenticationStatus. Possible values are 'ACTIVE',
	 * 'CREATED', 'DELETED', 'LOCKED'.
	 * 
	 * @param imsi
	 *            The subscriber identity
	 * @return Current authentication status as string.
	 * @throws AucException
	 *             An error occured while retrieving the authentication status.
	 */
	public String getAutheticationStatus(String imsi) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profile = profileDAO.findProfile(imsi);
		return profile.status.toString();
	}

	public boolean eraseProfile(String imsi) throws AucException {
		IProfileDAO profileDAO = ProfileDAOFactory.getInstance().getProfileDAO();
		ProfileTO profile = profileDAO.findProfile(imsi);
		if (!profile.status.equals(AuthenticationStatus.DELETED)) {
			return false;
		}
		profileDAO.deleteProfile(profile);
		return true;
	}
}
